package org.nobject.common.code.describer;

import static org.nobject.common.lang.StringUtils.isEmpty;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.nobject.common.lang.ClassUtils;
import org.nobject.common.lang.ListUtils;
import org.nobject.common.lang.StringUtils;

/**
 * RPC参数校验器
 *
 * @author bianrongjun
 * @version 1.0
 */
public class ReturnDescriber {
	/** 校验对应的参数索引 */
	public int idx=-1;
	/** 名称 */
	public String name;
	/** 参数名称或参数键值对应的名称 */
	public String comment;
	/** 是否能为空 */
	public boolean unnull=false;
	/** 校验 */
	public String validate;
	/** 长度 */
	public int length;
	/** 键值 */
	public String key;
	/** 键值来源 */
	public Class keyFrom;
	/** 子键来源 */
	public Class subKeyFrom;
	/** 使用Field校验 */
	public boolean vfield;
	/** 子描述s */
	public Object subDescs;
	/** 追加 */
	public boolean append;
	/** 返回类型 */
	public Class type;
	/** 每一个 */
	public boolean each;
	/** 子键值所有来源 */
	public boolean subAllkeyFrom;
	
	/**
	 * 构造函数 
	 */
	public ReturnDescriber(){
		
	}
	
	/**
	 * 构造函数 
	 * 第一层参数不会是键值
	 */
	public ReturnDescriber(Object desc) {
		this(
			DescriberUtils.getName		(desc), 
			DescriberUtils.getIdx		(desc), 
			DescriberUtils.getComment	(desc), 
			DescriberUtils.getUnnull	(desc), 
			DescriberUtils.getValidate	(desc), 
			DescriberUtils.getLength	(desc), 
			DescriberUtils.getKey		(desc),
			DescriberUtils.getKeyFrom	(desc),
			DescriberUtils.getSubKeyFrom(desc),
			DescriberUtils.getType		(desc),
			DescriberUtils.getVfield	(desc),
			DescriberUtils.getEach		(desc),
			DescriberUtils.getSubAllkeyFrom(desc),
			DescriberUtils.getSubs		(desc)
		);
	}
	
	/**
	 * 构造函数 
	 * @param name
	 * @param idx
	 * @param comment
	 * @param unnull
	 * @param validate
	 * @param length
	 * @param message
	 * @param key
	 * @param keyFrom
	 * @param subKeyFrom
	 * @param vfield
	 * @param filter
	 * @param subDescs
	 */
	public ReturnDescriber (
			String name,
			int idx, 
			String comment, 
			boolean unnull, 
			String validate, 
			int length, 
			String key,
			Class keyFrom,
			Class subKeyFrom,
			Class type,
			boolean vfield,
			boolean each,
			boolean subAllkeyFrom,
			Object subDescs) {
		this.name		=name;
		this.idx 		=idx;
		this.comment 	=comment;
		this.unnull 	=unnull;
		this.validate 	=validate;
		this.length 	=length;
		this.key 		=key;
		this.keyFrom	=keyFrom;
		this.subKeyFrom	=subKeyFrom;
		this.type		=type;
		this.vfield		=vfield;
		this.each		=each;
		this.subAllkeyFrom=subAllkeyFrom;
		this.subDescs	=subDescs;
	}
	
	/**
	 * 构造函数 
	 * @param idx
	 * @param comment
	 * @param unnull
	 * @param validate
	 * @param length
	 * @param message
	 * @param key
	 * @param vfield
	 * @param desc
	 * @param paramType
	 */
	public ReturnDescriber readKeyFrom() {
		//类型自动作为subkeyFrom
		if(this.type!=null){
			if(this.type.getAnnotation(ClassDesc.class)!=null){
				if(this.subKeyFrom==null||this.subKeyFrom==CNull.class){
					this.subKeyFrom=this.type;
				}
			}
		}
		
		//STN:fieldDesc
		if(this.keyFrom!=null&&this.keyFrom!=CNull.class&&!isEmpty(this.key)&&this.vfield){
			Field f=ClassUtils.getField(keyFrom, key);
			if(f==null) throw new RuntimeException("未在"+this.keyFrom.getName()+"找到"+key);
			FieldDesc fieldDesc=(FieldDesc)f.getAnnotation(FieldDesc.class);
			if(fieldDesc==null) throw new RuntimeException(this.keyFrom.getName()+"#"+key+"不含FieldDesc");
			
			if(StringUtils.isEmpty(this.comment)) 		this.comment	=fieldDesc.comment();
			if(StringUtils.isEmpty(this.validate)) 		this.validate	=fieldDesc.validate();
			if(this.length<0) 							this.length		=fieldDesc.length();
		}
		
		return this;
	}
	
	/** 
	 * toMap
	 * @return
	 */
	public Map toMap(){
		
		Map m=new LinkedHashMap();
		String [] ks={
			"idx"		,
			"name"		,
			"key"		,
	        "keyFrom"	,
	        "type"		,
			"comment"	,
			"unnull"	,
	        "validate"	,
	        "length" 	,
	        "subKeyFrom",	
	        "vfield"	,
	        "subDescs"	,
	        "each"		,
	        "subAllkeyFrom"
		};
		
		
		Class c=ReturnDescriber.class;
		
		for(String k:ks){
			
			Object o;
			try {
				o = c.getField(k).get(this);
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
			
			//转换Desc类型
			if(o instanceof Class){
				o=StringUtils.toString0(o);
			}
			
			if(o==null) continue;
			Class oc=o.getClass();
			
			//读取
			if(oc.isArray()&&oc.getComponentType().getSimpleName().endsWith("Desc")){
				
				//生成subAllkeyFrom
				List<ReturnDescriber> subRds=new LinkedList();
				if(subAllkeyFrom){
					Field [] fs=this.subKeyFrom.getDeclaredFields();
					for(Field f:fs){
						FieldDesc desc=f.getAnnotation(FieldDesc.class);
						if(desc==null) continue;
						ReturnDescriber rd=new ReturnDescriber(null,-1,null, true, null, -1, f.getName(), this.subKeyFrom, CNull.class, null, true, false, false, null);
						rd.readKeyFrom();
						subRds.add(rd);
					}
				}
				
				//
				Map<String,ReturnDescriber> mRds=subAllkeyFrom?ListUtils.extract2Map(subRds, "key"):null;
				int l=Array.getLength(o);
				for (int i = 0; i < l; i++) {
					Object subDesc		=Array.get(o,i);
					String key			=DescriberUtils.getKey(subDesc);
					ReturnDescriber rd	=new ReturnDescriber(subDesc);
					
					//判断是否删除来自subAllkeyFrom的重名字段
					ReturnDescriber oRd	=mRds!=null?mRds.get(key):null;
					if(oRd!=null){
						subRds.remove(oRd);
					}
					
					if(rd.keyFrom==null||rd.keyFrom.equals(CNull.class)){
						if(mRds!=null&&!mRds.containsKey(key)){
							//
						}else{
							rd.keyFrom=this.subKeyFrom;
						}
					}
					
					rd.readKeyFrom();
					subRds.add(rd);
				}
				
				if(subRds.size()>0){
					List subs=new LinkedList();
					for(ReturnDescriber rd:subRds){
						subs.add(rd.toMap());
					}
					o=subs;
				}
			}
			
			m.put(k, o);
		}
		
		return m;
	}
}
